home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 7 / Example 7.2 / skinnedMesh.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-07-27  |  6.0 KB  |  213 lines

  1. #include "skinnedMesh.h"
  2.  
  3. class BONE_HIERARCHY: public ID3DXAllocateHierarchy
  4. {
  5.     public:
  6.         STDMETHOD(CreateFrame)(THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame);
  7.         STDMETHOD(CreateMeshContainer)(THIS_ LPCTSTR Name, CONST D3DXMESHDATA * pMeshData, CONST D3DXMATERIAL * pMaterials, CONST D3DXEFFECTINSTANCE * pEffectInstances, DWORD NumMaterials, CONST DWORD * pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER * ppNewMeshContainer);
  8.         STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree);
  9.         STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerBase);
  10. };
  11.  
  12. HRESULT BONE_HIERARCHY::CreateFrame(LPCSTR Name, LPD3DXFRAME *ppNewFrame)
  13. {
  14.     BONE *newBone = new BONE;
  15.     memset(newBone, 0, sizeof(BONE));
  16.  
  17.     //Copy name
  18.     if(Name != NULL)
  19.     {
  20.         newBone->Name = new char[strlen(Name)+1];
  21.         strcpy(newBone->Name, Name);
  22.     }
  23.  
  24.     //Set the transformation matrices
  25.     D3DXMatrixIdentity(&newBone->TransformationMatrix);
  26.     D3DXMatrixIdentity(&newBone->CombinedTransformationMatrix);
  27.  
  28.     //Return the new bone...
  29.     *ppNewFrame = (D3DXFRAME*)newBone;
  30.  
  31.     return S_OK;
  32. }
  33.  
  34. HRESULT BONE_HIERARCHY::CreateMeshContainer(LPCSTR Name,
  35.                                             CONST D3DXMESHDATA *pMeshData,
  36.                                             CONST D3DXMATERIAL *pMaterials,
  37.                                             CONST D3DXEFFECTINSTANCE *pEffectInstances,
  38.                                             DWORD NumMaterials,
  39.                                             CONST DWORD *pAdjacency,
  40.                                             LPD3DXSKININFO pSkinInfo,
  41.                                             LPD3DXMESHCONTAINER *ppNewMeshContainer)
  42. {
  43.     //Just return a temporary mesh for now...
  44.     *ppNewMeshContainer = new BONEMESH;
  45.     memset(*ppNewMeshContainer, 0, sizeof(BONEMESH));
  46.  
  47.     return S_OK;
  48. }
  49.  
  50. HRESULT BONE_HIERARCHY::DestroyFrame(LPD3DXFRAME pFrameToFree) 
  51. {
  52.     if(pFrameToFree)
  53.     {
  54.         if(pFrameToFree->Name != NULL)
  55.             delete [] pFrameToFree->Name;
  56.         delete pFrameToFree;
  57.     }
  58.     pFrameToFree = NULL;
  59.  
  60.     return S_OK; 
  61. }
  62.  
  63. HRESULT BONE_HIERARCHY::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
  64. {
  65.     if(pMeshContainerBase != NULL)
  66.         delete pMeshContainerBase;
  67.  
  68.     return S_OK;
  69. }
  70.  
  71.  
  72. //////////////////////////////////////////////////////////////////////////////////////////////////
  73. //                                    SKINNED MESH                                                //
  74. //////////////////////////////////////////////////////////////////////////////////////////////////
  75.  
  76. struct VERTEX{
  77.     VERTEX();
  78.     VERTEX(D3DXVECTOR3 pos, D3DCOLOR col){position = pos; color = col;}
  79.     D3DXVECTOR3 position;
  80.     D3DCOLOR color;
  81.     static const DWORD FVF;
  82. };
  83.  
  84. const DWORD VERTEX::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
  85.  
  86. SKINNEDMESH::SKINNEDMESH()
  87. {
  88.     m_pRootBone = NULL;
  89.     m_pSphereMesh = NULL;
  90.     m_pAnimControl = NULL;
  91. }
  92.  
  93. SKINNEDMESH::~SKINNEDMESH()
  94. {
  95.     BONE_HIERARCHY boneHierarchy;
  96.     boneHierarchy.DestroyFrame(m_pRootBone);
  97.     if(m_pAnimControl)m_pAnimControl->Release();
  98. }
  99.  
  100. void SKINNEDMESH::Load(char fileName[], IDirect3DDevice9 *Dev)
  101. {
  102.     m_pDevice = Dev;
  103.     BONE_HIERARCHY boneHierarchy;
  104.  
  105.     D3DXLoadMeshHierarchyFromX(fileName, D3DXMESH_MANAGED, 
  106.                                m_pDevice, &boneHierarchy,
  107.                                NULL, &m_pRootBone, &m_pAnimControl);
  108.  
  109.     D3DXMATRIX i;
  110.     D3DXMatrixIdentity(&i);
  111.     UpdateMatrices((BONE*)m_pRootBone, &i);
  112.  
  113.     //Create Sphere
  114.     D3DXCreateSphere(m_pDevice, 0.07f, 10, 10, &m_pSphereMesh, NULL);
  115. }
  116.  
  117. void SKINNEDMESH::UpdateMatrices(BONE* bone, D3DXMATRIX *parentMatrix)
  118. {
  119.     if(bone == NULL)return;
  120.  
  121.     D3DXMatrixMultiply(&bone->CombinedTransformationMatrix,
  122.                        &bone->TransformationMatrix,
  123.                        parentMatrix);
  124.  
  125.     if(bone->pFrameSibling)UpdateMatrices((BONE*)bone->pFrameSibling, parentMatrix);
  126.     if(bone->pFrameFirstChild)UpdateMatrices((BONE*)bone->pFrameFirstChild, &bone->CombinedTransformationMatrix);
  127. }
  128.  
  129. void SKINNEDMESH::RenderSkeleton(BONE* bone, BONE *parent, D3DXMATRIX world)
  130. {
  131.     //Temporary function to render the bony hierarchy
  132.  
  133.     if(world == NULL)return;
  134.     if(bone == NULL)bone = (BONE*)m_pRootBone;
  135.  
  136.     D3DXMATRIX r, s;
  137.     D3DXMatrixRotationYawPitchRoll(&r, -D3DX_PI * 0.5f, 0.0f, 0.0f);
  138.  
  139.     //Draw Sphere
  140.     m_pDevice->SetRenderState(D3DRS_LIGHTING, true);
  141.     m_pDevice->SetTransform(D3DTS_WORLD, &(r * bone->CombinedTransformationMatrix * world));
  142.     if(bone->Name != NULL)m_pSphereMesh->DrawSubset(0);
  143.  
  144.     //Draw line between bones
  145.     if(parent != NULL && bone->Name != NULL && parent->Name != NULL)
  146.     {
  147.         D3DXMATRIX w1 = bone->CombinedTransformationMatrix;
  148.         D3DXMATRIX w2 = parent->CombinedTransformationMatrix;
  149.  
  150.         //Extract translation
  151.         D3DXVECTOR3 thisBone = D3DXVECTOR3(w1(3, 0), w1(3, 1), w1(3, 2));
  152.         D3DXVECTOR3 ParentBone = D3DXVECTOR3(w2(3, 0), w2(3, 1), w2(3, 2));
  153.  
  154.         if(D3DXVec3Length(&(thisBone - ParentBone)) < 2.0f)
  155.         {
  156.             m_pDevice->SetTransform(D3DTS_WORLD, &world);
  157.             VERTEX vert[] = {VERTEX(ParentBone, 0xffff0000), VERTEX(thisBone, 0xff00ff00)};
  158.             m_pDevice->SetRenderState(D3DRS_LIGHTING, false);
  159.             m_pDevice->SetFVF(VERTEX::FVF);
  160.             m_pDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, 1, &vert[0], sizeof(VERTEX));
  161.         }
  162.     }
  163.  
  164.     if(bone->pFrameSibling)RenderSkeleton((BONE*)bone->pFrameSibling, parent, world);
  165.     if(bone->pFrameFirstChild)RenderSkeleton((BONE*)bone->pFrameFirstChild, bone, world);
  166. }
  167.  
  168. void SKINNEDMESH::SetPose(D3DXMATRIX world, ID3DXAnimationController* animControl, float time)
  169. {
  170.     if(animControl != NULL)
  171.         animControl->AdvanceTime(time, NULL);
  172.     else m_pAnimControl->AdvanceTime(time, NULL);
  173.  
  174.     UpdateMatrices((BONE*)m_pRootBone, &world);
  175. }
  176.  
  177. void SKINNEDMESH::SetAnimation(char name[])
  178. {
  179.     ID3DXAnimationSet *anim = NULL;
  180.  
  181.     for(int i=0;i<m_pAnimControl->GetMaxNumAnimationSets();i++)
  182.     {
  183.         anim = NULL;
  184.         m_pAnimControl->GetAnimationSet(i, &anim);
  185.  
  186.         if(anim != NULL)
  187.         {
  188.             if(strcmp(name, anim->GetName()) == 0)
  189.                 m_pAnimControl->SetTrackAnimationSet(0, anim);
  190.             anim->Release();
  191.         }
  192.     }
  193. }
  194.  
  195. std::vector<std::string> SKINNEDMESH::GetAnimations()
  196. {
  197.     ID3DXAnimationSet *anim = NULL;
  198.     std::vector<std::string> animations;
  199.  
  200.     for(int i=0;i<m_pAnimControl->GetMaxNumAnimationSets();i++)
  201.     {
  202.         anim = NULL;
  203.         m_pAnimControl->GetAnimationSet(i, &anim);
  204.  
  205.         if(anim != NULL)
  206.         {
  207.             animations.push_back(anim->GetName());
  208.             anim->Release();
  209.         }
  210.     }
  211.  
  212.     return animations;
  213. }